home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / SOURCE / LIBPNG / PNGWRITE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-06  |  20.1 KB  |  667 lines  |  [TEXT/CWIE]

  1.  
  2. /* pngwrite.c - general routines to write a png file
  3.  
  4.    libpng 1.0 beta 4 - version 0.90
  5.    For conditions of distribution and use, see copyright notice in png.h
  6.    Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  7.    January 10, 1997
  8.    */
  9.  
  10. /* get internal access to png.h */
  11. #define PNG_INTERNAL
  12. #include "png.h"
  13.  
  14. /* Writes all the png information.  This is the suggested way to use
  15.    the library.  If you have a new chunk to add, make a function to
  16.    write it, and put it in the correct location here.  If you want
  17.    the chunk written after the image data, put it in png_write_end().
  18.    I strongly encurage you to supply a PNG_INFO_ flag, and check
  19.    info_ptr->valid before writing the chunk, as that will keep the code
  20.    from breaking if you want to just write a plain png file.
  21.    If you have long comments, I suggest writing them in png_write_end(),
  22.    and compressing them. */
  23. void
  24. png_write_info(png_structp png_ptr, png_infop info_ptr)
  25. {
  26.    png_write_sig(png_ptr); /* write PNG signature */
  27.    /* write IHDR information. */
  28.    png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
  29.       info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
  30.       info_ptr->filter_type, info_ptr->interlace_type);
  31.    /* the rest of these check to see if the valid field has the appropriate
  32.       flag set, and if it does, writes the chunk. */
  33. #if defined(PNG_WRITE_gAMA_SUPPORTED)
  34.    if (info_ptr->valid & PNG_INFO_gAMA)
  35.       png_write_gAMA(png_ptr, info_ptr->gamma);
  36. #endif
  37. #if defined(PNG_WRITE_sBIT_SUPPORTED)
  38.    if (info_ptr->valid & PNG_INFO_sBIT)
  39.       png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
  40. #endif
  41. #if defined(PNG_WRITE_cHRM_SUPPORTED)
  42.    if (info_ptr->valid & PNG_INFO_cHRM)
  43.       png_write_cHRM(png_ptr,
  44.          info_ptr->x_white, info_ptr->y_white,
  45.          info_ptr->x_red, info_ptr->y_red,
  46.          info_ptr->x_green, info_ptr->y_green,
  47.          info_ptr->x_blue, info_ptr->y_blue);
  48. #endif
  49.    if (info_ptr->valid & PNG_INFO_PLTE)
  50.       png_write_PLTE(png_ptr, info_ptr->palette, info_ptr->num_palette);
  51.    else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  52.       png_error(png_ptr, "Valid palette required for paletted images\n");
  53. #if defined(PNG_WRITE_tRNS_SUPPORTED)
  54.    if (info_ptr->valid & PNG_INFO_tRNS)
  55.       png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values),
  56.          info_ptr->num_trans, info_ptr->color_type);
  57. #endif
  58. #if defined(PNG_WRITE_bKGD_SUPPORTED)
  59.    if (info_ptr->valid & PNG_INFO_bKGD)
  60.       png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
  61. #endif
  62. #if defined(PNG_WRITE_hIST_SUPPORTED)
  63.    if (info_ptr->valid & PNG_INFO_hIST)
  64.       png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
  65. #endif
  66. #if defined(PNG_WRITE_pHYs_SUPPORTED)
  67.    if (info_ptr->valid & PNG_INFO_pHYs)
  68.       png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
  69.          info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
  70. #endif
  71. #if defined(PNG_WRITE_oFFs_SUPPORTED)
  72.    if (info_ptr->valid & PNG_INFO_oFFs)
  73.       png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
  74.          info_ptr->offset_unit_type);
  75. #endif
  76. #if defined(PNG_WRITE_tIME_SUPPORTED)
  77.    if (info_ptr->valid & PNG_INFO_tIME)
  78.    {
  79.       png_write_tIME(png_ptr, &(info_ptr->mod_time));
  80.       png_ptr->flags |= PNG_FLAG_WROTE_tIME;
  81.    }
  82. #endif
  83. #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
  84.    /* Check to see if we need to write text chunks */
  85.    if (info_ptr->num_text)
  86.    {
  87.       int i; /* local counter */
  88.  
  89.       /* loop through the text chunks */
  90.       for (i = 0; i < info_ptr->num_text; i++)
  91.       {
  92.          /* if chunk is compressed */
  93.          if (info_ptr->text[i].compression >= 0)
  94.          {
  95. #if defined(PNG_WRITE_zTXt_SUPPORTED)
  96.             /* write compressed chunk */
  97.             png_write_zTXt(png_ptr, info_ptr->text[i].key,
  98.                info_ptr->text[i].text, info_ptr->text[i].text_length,
  99.                info_ptr->text[i].compression);
  100. #else
  101.             png_warning(png_ptr, "Unable to write compressed text\n");
  102. #endif
  103.          }
  104.          else
  105.          {
  106. #if defined(PNG_WRITE_tEXt_SUPPORTED)
  107.             /* write uncompressed chunk */
  108.             png_write_tEXt(png_ptr, info_ptr->text[i].key,
  109.                info_ptr->text[i].text, info_ptr->text[i].text_length);
  110. #else
  111.             png_warning(png_ptr, "Unable to write uncompressed text\n");
  112. #endif
  113.          }
  114.       }
  115.    }
  116. #endif
  117. }
  118.  
  119. /* writes the end of the png file.  If you don't want to write comments or
  120.    time information, you can pass NULL for info.  If you already wrote these
  121.    in png_write_info(), do not write them again here.  If you have long
  122.    comments, I suggest writing them here, and compressing them. */
  123. void
  124. png_write_end(png_structp png_ptr, png_infop info_ptr)
  125. {
  126.    if (!(png_ptr->mode & PNG_HAVE_IDAT))
  127.       png_error(png_ptr, "No IDATs written into file");
  128.  
  129.    /* see if user wants us to write information chunks */
  130.    if (info_ptr)
  131.    {
  132. #if defined(PNG_WRITE_tIME_SUPPORTED)
  133.       /* check to see if user has supplied a time chunk */
  134.       if (info_ptr->valid & PNG_INFO_tIME &&
  135.          !(png_ptr->flags & PNG_FLAG_WROTE_tIME))
  136.          png_write_tIME(png_ptr, &(info_ptr->mod_time));
  137. #endif
  138. #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
  139.       /* check to see if we need to write comment chunks */
  140.       if (info_ptr->num_text)
  141.       {
  142.          int i; /* local index variable */
  143.  
  144.          /* loop through comment chunks */
  145.          for (i = 0; i < info_ptr->num_text; i++)
  146.          {
  147. #if defined(PNG_WRITE_zTXt_SUPPORTED)
  148.             /* check to see if comment is to be compressed */
  149.             if (info_ptr->text[i].compression >= 0)
  150.             {
  151.                /* write compressed chunk */
  152.                png_write_zTXt(png_ptr, info_ptr->text[i].key,
  153.                   info_ptr->text[i].text, info_ptr->text[i].text_length,
  154.                   info_ptr->text[i].compression);
  155.             }
  156. #if defined(PNG_WRITE_tEXt_SUPPORTED)
  157.             else
  158. #endif
  159. #endif
  160. #if defined(PNG_WRITE_tEXt_SUPPORTED)
  161.             {
  162.                /* write uncompressed chunk */
  163.                png_write_tEXt(png_ptr, info_ptr->text[i].key,
  164.                   info_ptr->text[i].text, info_ptr->text[i].text_length);
  165.             }
  166. #endif
  167.          }
  168.       }
  169. #endif
  170.    }
  171.  
  172.    png_ptr->mode |= PNG_AFTER_IDAT;
  173.  
  174.    /* write end of png file */
  175.    png_write_IEND(png_ptr);
  176. }
  177.  
  178. #if defined(PNG_WRITE_tIME_SUPPORTED)
  179. void
  180. png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
  181. {
  182.    ptime->year = (png_uint_16)(1900 + ttime->tm_year);
  183.    ptime->month = (png_byte)(ttime->tm_mon + 1);
  184.    ptime->day = (png_byte)ttime->tm_mday;
  185.    ptime->hour = (png_byte)ttime->tm_hour;
  186.    ptime->minute = (png_byte)ttime->tm_min;
  187.    ptime->second = (png_byte)ttime->tm_sec;
  188. }
  189.  
  190. void
  191. png_convert_from_time_t(png_timep ptime, time_t ttime)
  192. {
  193.    struct tm *tbuf;
  194.  
  195.    tbuf = gmtime(&ttime);
  196.    png_convert_from_struct_tm(ptime, tbuf);
  197. }
  198. #endif
  199.  
  200. /* initialize png structure, and allocate any memory needed */
  201. png_structp
  202. png_create_write_struct(png_const_charp user_png_ver, voidp error_ptr,
  203.    png_error_ptr error_fn, png_error_ptr warn_fn)
  204. {
  205.    png_structp png_ptr;
  206. #ifdef USE_FAR_KEYWORD
  207.    jmp_buf jmpbuf;
  208. #endif
  209.    if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
  210.    {
  211.       return (png_structp)NULL;
  212.    }
  213. #ifdef USE_FAR_KEYWORD
  214.    if (setjmp(jmpbuf))
  215. #else
  216.    if (setjmp(png_ptr->jmpbuf))
  217. #endif
  218.    {
  219.       png_free(png_ptr, png_ptr->zbuf);
  220.       png_destroy_struct(png_ptr);
  221.       return (png_structp)NULL;
  222.    }
  223. #ifdef USE_FAR_KEYWORD
  224.    png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
  225. #endif
  226.    png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
  227.  
  228.    if (user_png_ver == NULL || png_strcmp(user_png_ver, png_libpng_ver))
  229.    {
  230.       if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0])
  231.       {
  232.          png_error(png_ptr, "Incompatible libpng versions");
  233.       }
  234.       else
  235.       {
  236.          png_warning(png_ptr, "Different libpng versions");
  237.       }
  238.    }
  239.  
  240.    /* initialize zbuf - compression buffer */
  241.    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
  242.    png_ptr->zbuf = png_malloc(png_ptr, png_ptr->zbuf_size);
  243.  
  244.    png_set_write_fn(png_ptr, NULL, NULL, NULL);
  245.  
  246.    return (png_ptr);
  247. }
  248.  
  249.  
  250. /* initialize png structure, and allocate any memory needed */
  251. void
  252. png_write_init(png_structp png_ptr)
  253. {
  254.    jmp_buf tmp_jmp; /* to save current jump buffer */
  255.  
  256.    /* save jump buffer and error functions */
  257.    png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
  258.  
  259.    /* reset all variables to 0 */
  260.    png_memset(png_ptr, 0, sizeof (png_struct));
  261.  
  262.    /* restore jump buffer */
  263.    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
  264.  
  265.    /* initialize zbuf - compression buffer */
  266.    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
  267.    png_ptr->zbuf = png_malloc(png_ptr, png_ptr->zbuf_size);
  268.    png_set_write_fn(png_ptr, NULL, NULL, NULL);
  269. }
  270.  
  271. /* write a few rows of image data.  If the image is interlaced,
  272.    either you will have to write the 7 sub images, or, if you
  273.    have called png_set_interlace_handling(), you will have to
  274.    "write" the image seven times */
  275. void
  276. png_write_rows(png_structp png_ptr, png_bytepp row,
  277.    png_uint_32 num_rows)
  278. {
  279.    png_uint_32 i; /* row counter */
  280.    png_bytepp rp; /* row pointer */
  281.  
  282.    /* loop through the rows */
  283.    for (i = 0, rp = row; i < num_rows; i++, rp++)
  284.    {
  285.       png_write_row(png_ptr, *rp);
  286.    }
  287. }
  288.  
  289. /* write the image.  You only need to call this function once, even
  290.    if you are writing an interlaced image. */
  291. void
  292. png_write_image(png_structp png_ptr, png_bytepp image)
  293. {
  294.    png_uint_32 i; /* row index */
  295.    int pass, num_pass; /* pass variables */
  296.    png_bytepp rp; /* points to current row */
  297.  
  298.    /* intialize interlace handling.  If image is not interlaced,
  299.       this will set pass to 1 */
  300.    num_pass = png_set_interlace_handling(png_ptr);
  301.    /* loop through passes */
  302.    for (pass = 0; pass < num_pass; pass++)
  303.    {
  304.       /* loop through image */
  305.       for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
  306.       {
  307.          png_write_row(png_ptr, *rp);
  308.       }
  309.    }
  310. }
  311.  
  312. /* called by user to write a row of image data */
  313. void
  314. png_write_row(png_structp png_ptr, png_bytep row)
  315. {
  316.    /* initialize transformations and other stuff if first time */
  317.    if (png_ptr->row_number == 0 && png_ptr->pass == 0)
  318.    {
  319.       png_write_start_row(png_ptr);
  320.    }
  321.  
  322. #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
  323.    /* if interlaced and not interested in row, return */
  324.    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
  325.    {
  326.       switch (png_ptr->pass)
  327.       {
  328.          case 0:
  329.             if (png_ptr->row_number & 7)
  330.             {
  331.                png_write_finish_row(png_ptr);
  332.                return;
  333.             }
  334.             break;
  335.          case 1:
  336.             if ((png_ptr->row_number & 7) || png_ptr->width < 5)
  337.             {
  338.                png_write_finish_row(png_ptr);
  339.                return;
  340.             }
  341.             break;
  342.          case 2:
  343.             if ((png_ptr->row_number & 7) != 4)
  344.             {
  345.                png_write_finish_row(png_ptr);
  346.                return;
  347.             }
  348.             break;
  349.          case 3:
  350.             if ((png_ptr->row_number & 3) || png_ptr->width < 3)
  351.             {
  352.                png_write_finish_row(png_ptr);
  353.                return;
  354.             }
  355.             break;
  356.          case 4:
  357.             if ((png_ptr->row_number & 3) != 2)
  358.             {
  359.                png_write_finish_row(png_ptr);
  360.                return;
  361.             }
  362.             break;
  363.          case 5:
  364.             if ((png_ptr->row_number & 1) || png_ptr->width < 2)
  365.             {
  366.                png_write_finish_row(png_ptr);
  367.                return;
  368.             }
  369.             break;
  370.          case 6:
  371.             if (!(png_ptr->row_number & 1))
  372.             {
  373.                png_write_finish_row(png_ptr);
  374.                return;
  375.             }
  376.             break;
  377.       }
  378.    }
  379. #endif
  380.  
  381.    /* set up row info for transformations */
  382.    png_ptr->row_info.color_type = png_ptr->color_type;
  383.    png_ptr->row_info.width = png_ptr->usr_width;
  384.    png_ptr->row_info.channels = png_ptr->usr_channels;
  385.    png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth;
  386.    png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
  387.       png_ptr->row_info.channels);
  388.    png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
  389.       (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
  390.  
  391.    /* copy users row into buffer, leaving room for filter byte */
  392.    png_memcpy(png_ptr->row_buf + 1, row, (png_size_t)png_ptr->row_info.rowbytes);
  393.  
  394. #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
  395.    /* handle interlacing */
  396.    if (png_ptr->interlaced && png_ptr->pass < 6 &&
  397.       (png_ptr->transformations & PNG_INTERLACE))
  398.    {
  399.       png_do_write_interlace(&(png_ptr->row_info),
  400.          png_ptr->row_buf + 1, png_ptr->pass);
  401.       /* this should always get caught above, but still ... */
  402.       if (!(png_ptr->row_info.width))
  403.       {
  404.          png_write_finish_row(png_ptr);
  405.          return;
  406.       }
  407.    }
  408. #endif
  409.  
  410.    /* handle other transformations */
  411.    if (png_ptr->transformations)
  412.       png_do_write_transformations(png_ptr);
  413.  
  414.    /* find a filter if necessary, filter the row and write it out */
  415.    png_write_find_filter(png_ptr, &(png_ptr->row_info));
  416. }
  417.  
  418. #if defined(PNG_WRITE_FLUSH_SUPPORTED)
  419. /* Set the automatic flush interval or 0 to turn flushing off */
  420. void
  421. png_set_flush(png_structp png_ptr, int nrows)
  422. {
  423.    png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
  424. }
  425.  
  426. /* flush the current output buffers now */
  427. void
  428. png_write_flush(png_structp png_ptr)
  429. {
  430.    int wrote_IDAT;
  431.  
  432.    /* We have already written out all of the data */
  433.    if (png_ptr->row_number >= png_ptr->num_rows)
  434.      return;
  435.  
  436.    do
  437.    {
  438.       int ret;
  439.  
  440.       /* compress the data */
  441.       ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH);
  442.       wrote_IDAT = 0;
  443.  
  444.       /* check for compression errors */
  445.       if (ret != Z_OK)
  446.       {
  447.          if (png_ptr->zstream.msg)
  448.             png_error(png_ptr, png_ptr->zstream.msg);
  449.          else
  450.             png_error(png_ptr, "zlib error");
  451.       }
  452.  
  453.       if (!png_ptr->zstream.avail_out)
  454.       {
  455.          /* write the IDAT and reset the zlib output buffer */
  456.          png_write_IDAT(png_ptr, png_ptr->zbuf,
  457.                         png_ptr->zbuf_size);
  458.          png_ptr->zstream.next_out = png_ptr->zbuf;
  459.          png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
  460.          wrote_IDAT = 1;
  461.       }
  462.    } while(wrote_IDAT == 1);
  463.  
  464.    /* If there is any data left to be output, write it into a new IDAT */
  465.    if (png_ptr->zbuf_size != png_ptr->zstream.avail_out)
  466.    {
  467.       /* write the IDAT and reset the zlib output buffer */
  468.       png_write_IDAT(png_ptr, png_ptr->zbuf,
  469.                      png_ptr->zbuf_size - png_ptr->zstream.avail_out);
  470.       png_ptr->zstream.next_out = png_ptr->zbuf;
  471.       png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
  472.    }
  473.    png_ptr->flush_rows = 0;
  474.    png_flush(png_ptr);
  475. }
  476. #endif /* PNG_WRITE_FLUSH_SUPPORTED */
  477.  
  478. /* free all memory used by the write */
  479. void
  480. png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
  481. {
  482.    png_structp png_ptr = NULL;
  483.    png_infop info_ptr = NULL;
  484.  
  485.    if (png_ptr_ptr)
  486.       png_ptr = *png_ptr_ptr;
  487.  
  488.    if (info_ptr_ptr)
  489.       info_ptr = *info_ptr_ptr;
  490.  
  491.    if (info_ptr)
  492.    {
  493.       png_destroy_struct((png_voidp)info_ptr);
  494.       *info_ptr_ptr = (png_infop)NULL;
  495.    }
  496.  
  497.    if (png_ptr)
  498.    {
  499.       png_write_destroy(png_ptr);
  500.       png_destroy_struct((png_voidp)png_ptr);
  501.       *png_ptr_ptr = (png_structp)NULL;
  502.    }
  503. }
  504.  
  505.  
  506. /* free any memory used in png struct (old method) */
  507. void
  508. png_write_destroy(png_structp png_ptr)
  509. {
  510.    jmp_buf tmp_jmp; /* save jump buffer */
  511.    png_error_ptr error_fn;
  512.    png_error_ptr warning_fn;
  513.    png_voidp error_ptr;
  514.  
  515.    /* free any memory zlib uses */
  516.    deflateEnd(&png_ptr->zstream);
  517.  
  518.    /* free our memory.  png_free checks NULL for us. */
  519.    png_free(png_ptr, png_ptr->zbuf);
  520.    png_free(png_ptr, png_ptr->row_buf);
  521.    png_free(png_ptr, png_ptr->prev_row);
  522.    png_free(png_ptr, png_ptr->sub_row);
  523.    png_free(png_ptr, png_ptr->up_row);
  524.    png_free(png_ptr, png_ptr->avg_row);
  525.    png_free(png_ptr, png_ptr->paeth_row);
  526.  
  527.    /* reset structure */
  528.    png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
  529.  
  530.    error_fn = png_ptr->error_fn;
  531.    warning_fn = png_ptr->warning_fn;
  532.    error_ptr = png_ptr->error_ptr;
  533.  
  534.    png_memset(png_ptr, 0, sizeof (png_struct));
  535.  
  536.    png_ptr->error_fn = error_fn;
  537.    png_ptr->warning_fn = warning_fn;
  538.    png_ptr->error_ptr = error_ptr;
  539.  
  540.    png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
  541. }
  542.  
  543. /* Allow the application to select one or more filters to use */
  544. void
  545. png_set_filter(png_structp png_ptr, int method, int filters)
  546. {
  547.    /* We allow 'method' only for future expansion of the base filter method */
  548.    if (method == 0)
  549.    {
  550.       switch (filters & (PNG_ALL_FILTERS | 0x07))
  551.       {
  552.          case 5:
  553.          case 6:
  554.          case 7: png_warning(png_ptr, "Unknown custom row filter for method 0");
  555.          case 0: png_ptr->do_filter = PNG_FILTER_NONE; break;
  556.          case 1: png_ptr->do_filter = PNG_FILTER_SUB; break;
  557.          case 2: png_ptr->do_filter = PNG_FILTER_UP; break;
  558.          case 3: png_ptr->do_filter = PNG_FILTER_AVG; break;
  559.          case 4: png_ptr->do_filter = PNG_FILTER_PAETH; break;
  560.          default: png_ptr->do_filter = (png_byte)filters; break;
  561.       }
  562.  
  563.       /* If we have allocated the row_buf, then we should have also allocated
  564.        * all of the filter buffers that have been selected.
  565.        */
  566.       if (png_ptr->row_buf)
  567.       {
  568.          if (png_ptr->do_filter & PNG_FILTER_SUB && !(png_ptr->sub_row))
  569.          {
  570.             png_ptr->sub_row = (png_bytep )png_malloc(png_ptr,
  571.                png_ptr->rowbytes + 1);
  572.             png_ptr->sub_row[0] = 1;  /* Set the row filter type */
  573.          }
  574.  
  575.          if (png_ptr->do_filter & PNG_FILTER_UP && !(png_ptr->up_row))
  576.          {
  577.             if (!(png_ptr->prev_row))
  578.             {
  579.                png_warning(png_ptr, "Can't to add up filter after starting");
  580.                png_ptr->do_filter &= ~PNG_FILTER_UP;
  581.             }
  582.             else
  583.             {
  584.                png_ptr->up_row = (png_bytep )png_malloc(png_ptr,
  585.                   png_ptr->rowbytes + 1);
  586.                png_ptr->up_row[0] = 2;  /* Set the row filter type */
  587.             }
  588.          }
  589.  
  590.          if (png_ptr->do_filter & PNG_FILTER_AVG && !(png_ptr->avg_row))
  591.          {
  592.             if (!(png_ptr->prev_row))
  593.             {
  594.                png_warning(png_ptr, "Can't add average filter after starting");
  595.                png_ptr->do_filter &= ~PNG_FILTER_AVG;
  596.             }
  597.             else
  598.             {
  599.                png_ptr->up_row = (png_bytep )png_malloc(png_ptr,
  600.                   png_ptr->rowbytes + 1);
  601.                png_ptr->up_row[0] = 3;  /* Set the row filter type */
  602.             }
  603.          }
  604.  
  605.          if (png_ptr->do_filter & PNG_FILTER_PAETH && !(png_ptr->paeth_row))
  606.          {
  607.             if (!(png_ptr->prev_row))
  608.             {
  609.                png_warning(png_ptr, "Can't add Paeth filter after starting");
  610.                png_ptr->do_filter &= ~PNG_FILTER_PAETH;
  611.             }
  612.             else
  613.             {
  614.                png_ptr->paeth_row = (png_bytep )png_malloc(png_ptr,
  615.                   png_ptr->rowbytes + 1);
  616.                png_ptr->paeth_row[0] = 4;  /* Set the row filter type */
  617.             }
  618.          }
  619.  
  620.          if (png_ptr->do_filter == PNG_NO_FILTERS)
  621.             png_ptr->do_filter = PNG_FILTER_NONE;
  622.       }
  623.    }
  624.    else
  625.      png_error(png_ptr, "Unknown custom filter method");
  626. }
  627.  
  628. void
  629. png_set_compression_level(png_structp png_ptr, int level)
  630. {
  631.    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
  632.    png_ptr->zlib_level = level;
  633. }
  634.  
  635. void
  636. png_set_compression_mem_level(png_structp png_ptr, int mem_level)
  637. {
  638.    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
  639.    png_ptr->zlib_mem_level = mem_level;
  640. }
  641.  
  642. void
  643. png_set_compression_strategy(png_structp png_ptr, int strategy)
  644. {
  645.    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
  646.    png_ptr->zlib_strategy = strategy;
  647. }
  648.  
  649. void
  650. png_set_compression_window_bits(png_structp png_ptr, int window_bits)
  651. {
  652.    if (window_bits > 15)
  653.       png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
  654.    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
  655.    png_ptr->zlib_window_bits = window_bits;
  656. }
  657.  
  658. void
  659. png_set_compression_method(png_structp png_ptr, int method)
  660. {
  661.    if (method != 8)
  662.       png_warning(png_ptr, "Only compression method 8 is supported by PNG");
  663.    png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
  664.    png_ptr->zlib_method = method;
  665. }
  666.  
  667.